package main

import (
	"errors"
	"fmt"
)

func main() {
	/*fmt.Println("Hello" + " world!")
	fmt.Println("1+1", 1+1)

	var a string = "initial"
	fmt.Println(a);
	var b, c int = 1, 2
	var d = true
	var e int
	f := "short"

	fmt.Println(b, c, d, e, f)

	const n = 500000000
	const g = 3e20 / n
	fmt.Println(g)
	fmt.Println(int64(g))

	i := 1
	for i <= 3 {
		fmt.Println(i)
		i = i + 1
	}

	for j := 7; j <= 9; j++ {
		fmt.Println(j)
	}

	for {
		fmt.Println("loop")
		break
	}

	if 7%2 == 0 {
		fmt.Println("7 is even")
	} else {
		fmt.Println("7 is odd")
	}

	if 8%4 == 0 {
		fmt.Println("8 is devisialbe by 4")
	}

	if num := 9; num < 0 {
		fmt.Println(num, "is negative")
	} else if num < 10 {
		fmt.Println(num, "has one digit")
	} else {
		fmt.Println(num, "has multiple digits")
	}

	num := 2;
	fmt.Print("wirte ", num, " as ")
	switch num {
	case 1:
		fmt.Println("one")
	case 2:
		fmt.Println("two")
	case 3:
		fmt.Println("three")
	}

	switch time.Now().Weekday() {
	case time.Saturday, time.Sunday:
		fmt.Println("It's the weekend")
	default:
		fmt.Println("It's a weekday")
	}

	t := time.Now()
	switch {
	case t.Hour() < 12:
		fmt.Println("It's before noon")
	default:
		fmt.Println("It's after noon")
	}

	var arr [5]int
	fmt.Println("emp: ", arr)
	arr[4] = 100
	fmt.Println("set:", arr)
	fmt.Println("get:", arr[4])
	fmt.Println("len:", len(arr))

	brr := [5]int{1, 2, 3, 4, 5}
	fmt.Println("dcl:", brr)

	var twoD [2][3]int
	for i := 0; i < 2; i++ {
		for j := 0; j < 3; j++ {
			twoD[i][j] = i + j
		}
	}
	fmt.Println(twoD)

	slice := make([]string, 3)
	fmt.Println("emp:", slice)
	slice[0] = "a"
	slice[1] = "b"
	slice[2] = "c"
	fmt.Println("set:", slice)
	fmt.Println("get:", slice[2])
	fmt.Println("len", len(slice))

	slice = append(slice, "d")
	slice = append(slice, "e", "f")
	fmt.Println("apd:", slice)

	clice := make([]string, len(slice))
	copy(clice, slice)
	fmt.Println("cpy:", clice)

	llice := slice[2:5]
	fmt.Println("sl1", llice)

	llice = slice[:5]
	fmt.Println("sl2", llice)

	llice = slice[2:]
	fmt.Println("sl3", llice)

	tlice := []string{"g", "h", "t"}
	fmt.Println("dcl:", tlice)

	twoDlice := make([][]int, 3)
	for i := 0; i < 3; i++ {
		innerLen := i + 1
		twoDlice[i] = make([]int, innerLen)
		for j := 0; j < innerLen; j++ {
			twoDlice[i][j] = i + j
		}
	}
	fmt.Println("2d:", twoDlice)

	mmap := make(map[string]int)
	mmap["k1"] = 7
	mmap["k2"] = 7
	fmt.Println("map:", mmap)

	v1 := mmap["k1"]
	fmt.Println("v1:", v1)
	fmt.Println("len:", len(mmap))
	delete(mmap, "k2")
	fmt.Println("map:", len(mmap))

	_, prs := mmap["k2"]
	fmt.Println("prs:", prs)

	nmap := map[string]int{"foo": 1, "bar": 2}
	fmt.Println("map", nmap)

	nums := []int{2, 3, 4}
	sum := 0
	for _, num := range nums {
		sum += num
	}
	fmt.Println("sum:", sum)
	for i, num := range nums {
		if num == 3 {
			fmt.Println("index of 3:", i)
		}
	}

	kvs := map[string]string{"a": "apple", "b": "banana"}
	for k, v := range kvs {
		fmt.Printf("%s -> %s\n", k, v)
	}
	for irange, crange := range "go" {
		fmt.Println(irange, crange)
	}
	fmt.Println("func plus", plus(1, 2))
	a_multiple_return, b_multiple_return := vals()
	fmt.Println(a_multiple_return, b_multiple_return)
	_, c_multiple_return := vals()
	fmt.Println(c_multiple_return)
	sum_multiple_args(1, 2, 3)
	sum_multiple_args(1, 2, 3, 4)
	nums_multiple_args := []int{1, 2, 3, 4, 5}
	sum_multiple_args(nums_multiple_args...)

	nextIntClosure := intSeq()
	fmt.Println(nextIntClosure())
	fmt.Println(nextIntClosure())
	fmt.Println(nextIntClosure())
	newInts := nextIntClosure()
	fmt.Println(newInts)

	fmt.Println("fact:", fact(7))
	ptr_i := 1
	fmt.Println("initial:", ptr_i)
	zeroval(ptr_i);
	fmt.Println("zeroval:", ptr_i)
	zeroptr(&ptr_i);
	fmt.Println("zeroval:", ptr_i)
	fmt.Println(&ptr_i);
	type Person struct {
		name string
		age  int
	}
	fmt.Println(Person{"Bob", 20})
	fmt.Println(Person{name: "Alice", age: 20})
	fmt.Println(Person{name: "Fred"})
	fmt.Println(&Person{name: "Ann", age: 40})

	s := Person{name: "Sean", age: 50}
	fmt.Println(s.name)

	sp := &s
	fmt.Println(sp.age)
	sp.age = 51
	fmt.Println(sp.age)*/
	/*	r := rect{10, 15}
		println(r.area())
		println(r.perim())

		rp := &r
		println(rp.area())
		println(rp.perim())*/
	for _, i := range []int{7, 42} {
		if r, e := f1_error(i); e != nil {
			println("f1 failed:", e)
		} else {
			println("f1 worked", r)
		}
	}
	for _, i := range []int{7, 42} {
		if r, e := f2_error(i); e != nil {
			println("f2 failed:", e)
		} else {
			println("f2 worked", r)
		}
	}
	_,e:=f2_error(42)
	if ae,ok := e.(*argError); ok{
		println(ae.arg)
		println(ae.prob)
	}
}

func f1_error(arg int) (int, error) {
	if arg == 42 {
		return -1, errors.New("Can't work with 42")
	}
	return arg + 13, nil
}

type argError struct {
	arg  int
	prob string
}

func (e *argError) Error() string {
	return fmt.Sprintf("%d -> %s", e.arg, e.prob)
}
func f2_error(arg int) (int, error) {
	if arg == 42 {
		return -1, &argError{arg, "can't work with it"}
	}
	return arg + 13, nil
}

/*
type geometry interface {
	area() float64
	perim() float64
}
*/

/*type rect struct {
	width, height int
}

func (r *rect) area() int {
	return r.width * r.height
}
func (r *rect) perim() int {
	return 2*r.height + 2*r.width
}*/

/*func zeroval(ival int)      { ival = 0 }
func zeroptr(iptr *int)     { *iptr = 0 }
func plus(a int, b int) int { return a + b }
func vals() (int, int)      { return 3, 7 }
func sum_multiple_args(nums ...int) {
	fmt.Print(nums, " ")
	total := 0
	for _, num := range nums {
		total += num
	}
	fmt.Println(total)
}
func intSeq() func() int {
	i := 0
	return func() int {
		i += 1
		return i
	}
}
func fact(n int) int {
	if n == 0 {
		return 1
	} else {
		return n * fact(n-1)
	}
}*/
